package org.example;

import java.util.Random;

public class BlockingQueue {
    private int[] items=new int[1000];
    private volatile int size=0;
    private volatile int head=0;
    private volatile int tail=0;
    public void put(int value) throws InterruptedException {
        synchronized ( this){
            // 此处最好使⽤ while.
            // 否则 notifyAll 的时候, 该线程从 wait 中被唤醒,
            // 但是紧接着并未抢占到锁. 当锁被抢占的时候, 可能⼜已经队列满了
            // 就只能继续等待
            while (size==items.length){
                wait();
            }
            items[tail]=value;
            tail=(tail+1)%items.length;
            size++;
            notifyAll();
        }
    }
    public int take() throws InterruptedException {
        int ret=0;
        synchronized (this){
            while (size==0){
                wait();
            }
            ret=items[head];
            head=(head+1)%items.length;
            size--;
            notifyAll();
        }
        return ret;
    }
    public synchronized int size(){
        return size;
    }

    public static void main(String[] args) throws InterruptedException {
        BlockingQueue queue = new BlockingQueue();
        Thread customer=new Thread(()->{
            try {
                int value=queue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"消费者");
        customer.start();
        Thread producer=new Thread(()->{
            Random random = new Random();
            try {
                queue.put(random.nextInt());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"生产者");
        producer.start();
        customer.join();
        producer.join();
    }
}
